//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import React, { useEffect, useState } from 'react';
import { observer } from 'mobx-react';
import { Button, Card, Descriptions, Form, Input, message, Modal, Progress, Radio } from 'antd';
import { useRoadmapStores } from '../store';
import { NODE_SUB_TOPIC, NODE_TOPIC } from '@/api/roadmap_content';
import { TOPIC_STATE_DONE, TOPIC_STATE_SKIP } from '@/api/roadmap_state';
import type * as NoticeType from '@/api/notice_type';
import { emit } from "@tauri-apps/api/event";
import { ExportOutlined, FolderOpenOutlined } from '@ant-design/icons';
import { save as save_image } from '@tauri-apps/api/dialog';
import { toPng } from 'html-to-image';
import { writeBinaryFile, writeTextFile } from '@tauri-apps/api/fs';
import { getRectOfNodes, getTransformForBounds, useReactFlow } from 'reactflow';

interface ExportModalProps {
    onClose: () => void;
}

const ExportModal = (props: ExportModalProps) => {
    const roadmapStore = useRoadmapStores();
    const { getNodes } = useReactFlow();

    const [exportType, setExportType] = useState("image" as "image" | "data");
    const [destFilePath, setDestFilePath] = useState("");
    const [inExport, setInExport] = useState(false);

    const choicePath = async () => {
        const filePath = await save_image({
            title: "导出路径",
            filters: [{
                name: exportType == "image" ? "图片" : "数据文件",
                extensions: exportType == "image" ? ["png"] : ["lvup"],
            }],
        });
        if (filePath == null) {
            return;
        } else {
            setDestFilePath(filePath);
        }
    };

    const runExport = async () => {
        if (exportType == "image") {
            await runExportImage();
        } else if (exportType == "data") {
            await runExportData();
        }
    }

    const runExportImage = async () => {
        try {
            setInExport(true);
            const nodesBounds = getRectOfNodes(getNodes());
            const imageWidth = nodesBounds.width + 100;
            const imageHeight = nodesBounds.height + 100;
            const transform = getTransformForBounds(
                nodesBounds,
                imageWidth,
                imageHeight,
                0.1,
                2,
            );

            const data = await toPng(document.querySelector('.react-flow__viewport') as HTMLElement, {
                filter: node =>
                    !(
                        node?.classList?.contains('react-flow__minimap') ||
                        node?.classList?.contains('react-flow__controls')
                    ),
                backgroundColor: '#eee',
                width: imageWidth,
                height: imageHeight,
                style: {
                    width: String(imageWidth),
                    height: String(imageHeight),
                    transform: `translate(${transform[0]}px, ${transform[1]}px) scale(${transform[2]})`,
                },
            });
            const pos = data.indexOf(",");
            if (pos == -1) {
                return;
            }
            const imageDataStr = atob(data.substring(pos + 1));
            const imageData = [];
            for (let i = 0; i < imageDataStr.length; i++) {
                imageData.push(imageDataStr.charCodeAt(i));
            }
            await writeBinaryFile(destFilePath, Uint8Array.from(imageData));
            message.info("保存成功");
            props.onClose();
        } catch (e) {
            console.log(e);
            message.error("出错了");
        } finally {
            setInExport(false);
        };
    };

    const runExportData = async () => {
        const dataObj = {
            id: roadmapStore.roadmapInfo?.roadmap_id ?? "",
            name: roadmapStore.roadmapInfo?.basic_info.title ?? "",
            nodeList: roadmapStore.nodeList,
            edgeList: roadmapStore.edgeList,
        }
        try {
            setInExport(true);
            await writeTextFile(destFilePath, JSON.stringify(dataObj));
            message.info("保存成功");
            props.onClose();
        } catch (e) {
            console.log(e);
            message.error("出错了");
        } finally {
            setInExport(false);
        }
    };

    const checkFileType = () => {
        if (exportType == "image") {
            return destFilePath.endsWith(".png");
        } else if (exportType == "data") {
            return destFilePath.endsWith(".lvup");
        }
        return false;
    };

    return (
        <Modal open title="导出" mask={false}
            okText={inExport ? "导出中..." : "导出"} okButtonProps={{ disabled: (!checkFileType() || inExport) }}
            onCancel={e => {
                e.stopPropagation();
                e.preventDefault();
                props.onClose();
            }}
            onOk={e => {
                e.stopPropagation();
                e.preventDefault();
                runExport();
            }}>
            <Form>
                <Form.Item label="导出类型">
                    <Radio.Group options={[
                        {
                            label: "图片",
                            value: "image"
                        },
                        {
                            label: "数据文件",
                            value: "data"
                        },
                    ]} defaultValue={exportType} optionType="button" onChange={e => setExportType(e.target.value)} />
                </Form.Item>
                <Form.Item label="导出文件" help={(
                    <>
                        {(exportType == "image" && !destFilePath.endsWith(".png")) ? "图片文件必须是png" : undefined}
                        {(exportType == "data" && !destFilePath.endsWith(".lvup")) ? "数据文件必须是lvup" : undefined}
                    </>
                )}>
                    <Input value={destFilePath} onChange={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        setDestFilePath(e.target.value.trim());
                    }} status={checkFileType() == false ? "error" : ""}
                        addonAfter={<Button type="link" style={{ height: 20 }} icon={<FolderOpenOutlined />} onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            choicePath();
                        }} />} />
                </Form.Item>
            </Form>
        </Modal>
    );
};

const RoadmapInfoPanel = () => {
    const roadmapStore = useRoadmapStores();

    const [doneTopicCount, setDoneTopicCount] = useState(0);
    const [totalTopicCount, setTotalTopicCount] = useState(0);
    const [topicRatio, setTopicRatio] = useState(0);
    const [calcTopicOk, setCalcTopicOk] = useState(false);

    const [doneSubTopicCount, setDoneSubTopicCount] = useState(0);
    const [totalSubTopicCount, setTotalSubTopicCount] = useState(0);
    const [subTopicRatio, setSubTopicRatio] = useState(0);
    const [calcSubTopicOk, setCalcSubTopicOk] = useState(false);

    const [showExportModal, setShowExportModal] = useState(false);


    const calcTopicCount = () => {
        const topicNodeList = roadmapStore.nodeList.filter(item => item.basic_info.node_type == NODE_TOPIC);
        let skipCount = 0;
        let doneCount = 0;
        for (const topicNode of topicNodeList) {
            const state = roadmapStore.stateList.find(item => item.node_id == topicNode.node_id);
            if (state == undefined) {
                continue;
            }
            if (state.basic_info.state_data.TopicState?.state == TOPIC_STATE_SKIP) {
                skipCount += 1;
            } else if (state.basic_info.state_data.TopicState?.state == TOPIC_STATE_DONE) {
                doneCount += 1;
            }
        }
        const totalCount = topicNodeList.length - skipCount
        setTotalTopicCount(totalCount);
        setDoneTopicCount(doneCount);
        if (totalCount == 0) {
            setTopicRatio(0);
        } else {
            setTopicRatio(doneCount * 100 / totalCount);
        }
        setCalcTopicOk(true);
    };

    const calcSubTopicCount = () => {
        const topicNodeList = roadmapStore.nodeList.filter(item => item.basic_info.node_type == NODE_SUB_TOPIC);
        let skipCount = 0;
        let doneCount = 0;
        for (const topicNode of topicNodeList) {
            const state = roadmapStore.stateList.find(item => item.node_id == topicNode.node_id);
            if (state == undefined) {
                continue;
            }
            if (state.basic_info.state_data.TopicState?.state == TOPIC_STATE_SKIP) {
                skipCount += 1;
            } else if (state.basic_info.state_data.TopicState?.state == TOPIC_STATE_DONE) {
                doneCount += 1;
            }
        }
        const totalCount = topicNodeList.length - skipCount
        setTotalSubTopicCount(totalCount);
        setDoneSubTopicCount(doneCount);
        if (totalCount == 0) {
            setTopicRatio(0);
        } else {
            setSubTopicRatio(doneCount * 100 / totalCount);
        }
        setCalcSubTopicOk(true);
    };

    useEffect(() => {
        calcTopicCount();
        calcSubTopicCount();
    }, [roadmapStore.nodeList, roadmapStore.stateList]);

    useEffect(() => {
        if (calcTopicOk && calcSubTopicOk) {
            const notice: NoticeType.AllNotice = {
                ClientNotice: {
                    AccessRoadmapNotice: {
                        roadmapId: roadmapStore.roadmapId,
                        doneTopicCount: doneTopicCount,
                        totalTopicCount: totalTopicCount,
                        doneSubTopicCount: doneSubTopicCount,
                        totalSubTopicCount: totalSubTopicCount,
                    },
                }
            };
            emit("notice", notice);
        }
    }, [doneTopicCount, totalTopicCount, doneSubTopicCount, totalSubTopicCount, calcTopicOk, calcSubTopicOk]);

    return (
        <Card title="成长路线" headStyle={{ fontSize: "14px", fontWeight: 600 }}
            style={{ width: "250px", backgroundColor: "white", padding: "10px 10px" }}
            extra={
                <Button type="link" icon={<ExportOutlined />} title='导出'
                    onClick={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        setShowExportModal(true);
                    }} />
            }>
            <Descriptions column={1} labelStyle={{ width: "70px", justifyContent: "right" }}>
                <Descriptions.Item label="学习阶段">
                    <Progress percent={topicRatio} format={() => `${doneTopicCount}/${totalTopicCount}`} size='small' />
                </Descriptions.Item>
                <Descriptions.Item label="知识点">
                    <Progress percent={subTopicRatio} format={() => `${doneSubTopicCount}/${totalSubTopicCount}`} size='small' />
                </Descriptions.Item>
            </Descriptions>
            <pre style={{ whiteSpace: "pre-wrap", wordWrap: "break-word", padding: "10px 10px" }}>
                {roadmapStore.roadmapInfo?.basic_info.desc ?? ""}
            </pre>
            {showExportModal && <ExportModal onClose={() => setShowExportModal(false)} />}
        </Card>
    );
};

export default observer(RoadmapInfoPanel);